package sanshui.system.trade.factory.trade.riskCtr;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sanshui.system.trade.factory.trade.TradeSystemContext;
import sanshui.system.trade.factory.trade.strategy.StrategyCallType;
import sanshui.system.trade.factory.trade.strategy.StrategyResult;
import sanshui.system.trade.model.PositionAccModel;
import sanshui.system.trade.model.TradeAccountModel;
import sanshui.system.trade.util.TradePositionUtil;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class AbstractRiskStrategy implements IRiskStrategy {
    private static final Logger logger = LoggerFactory.getLogger(AbstractRiskStrategy.class);

    RiskCtrCode name = RiskCtrCode.DEFAULT;
    String desc = "";

    public AbstractRiskStrategy() {
    }

    public AbstractRiskStrategy(RiskCtrCode name) {
        this.name = name;
    }
    public AbstractRiskStrategy(RiskCtrCode name, String desc) {
        this.name = name;
        this.desc = desc;
    }

    @Override
    public RiskCtrCode getRiskName() {
        return name;
    }

    @Override
    public String getDesc() {
        return desc;
    }

    /**
     * 默认：
     * 买入: 平均分配金额后，买入最大值
     * 卖出: 全部卖出
     * */
    @Override
    public List<StrategyResult> exec(TradeSystemContext tradeSystemContext, List<StrategyResult> strategyResults) {
        List<StrategyResult> riskResult = new ArrayList<>();

        Map<String, StrategyResult> buyMap = new HashMap<>();
        Map<String, StrategyResult> sellMap = new HashMap<>();

        for (StrategyResult strategyResult : strategyResults) {
            if (StrategyCallType.SELL.compareTo(strategyResult.getStrategyCallType()) == 0) {
                sellMap.put(strategyResult.getCode(), strategyResult);
            }
            if (StrategyCallType.BUY.compareTo(strategyResult.getStrategyCallType()) == 0){
                buyMap.put(strategyResult.getCode(), strategyResult);
            }
        }

        sellMap.forEach((code, strategyResult) ->{
            this.sell(code, strategyResult, sellMap, tradeSystemContext);
            riskResult.add(strategyResult);
        });

        buyMap.forEach((code, strategyResult) ->{
            this.buy(code, strategyResult, buyMap, tradeSystemContext);
            riskResult.add(strategyResult);
        });
        return riskResult;
    }


    protected void sell(String code, StrategyResult strategyResult, Map<String, StrategyResult> sellMap, TradeSystemContext tradeSystemContext) {
        long numSg = strategyResult.getNum();
        if (numSg > 0){
            return;
        }

        PositionAccModel positionAccModel = tradeSystemContext.getHoldPositionMap().get(code);
        if (positionAccModel == null){
            strategyResult.setNum(0);
        } else {
            strategyResult.setNum(positionAccModel.getNumCanTrade());
        }
    }

    protected void buy(String code, StrategyResult strategyResult, Map<String, StrategyResult> buyMap, TradeSystemContext tradeSystemContext) {
        long numSg = strategyResult.getNum();
        if (numSg > 0){
            return;
        }

        TradeAccountModel accountInfo = tradeSystemContext.getAccount();
        Long cashValue = accountInfo.getCurrentCash();
        Long preCodeCashBuy = cashValue / buyMap.keySet().size() - 5000L; // 保留50元作为手续费
        Long num = preCodeCashBuy / strategyResult.getPrice();
        // A股
        long minNumAround = 100L;
        num = num / minNumAround * minNumAround;
        strategyResult.setCode(code);

        if (num < minNumAround) {
            logger.warn("可买入数量无效,code:{}, workerId:{}, num:{}",code, tradeSystemContext.getWorkerId(), num);
            strategyResult.setStrategyCallType(StrategyCallType.NOTHING);
            strategyResult.setNum(0L);
            strategyResult.setFee(0L);
            return;
        }
        strategyResult.setStrategyCallType(StrategyCallType.BUY);
        strategyResult.setNum(num);
    }
}
